#!/usr/bin/env node

// 批量修复：有参考号但状态为 failed/pending 的记录 → 标记为 booked，并补齐 booked_at
// 使用方法（Windows PowerShell）：
//   node app/tools/fix-booked-status.mjs            # 预览（dry-run）
//   node app/tools/fix-booked-status.mjs --apply    # 实际写库
// 可选参数：
//   --limit 200          仅处理最近更新的 N 条候选
//   --clear-error        同时清空 error_message 字段

import { existsSync } from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { PrismaClient } from '@prisma/client'

function parseArgs(argv) {
  const args = { apply: false, limit: 0, clearError: false, db: '' }
  for (let i = 2; i < argv.length; i++) {
    const a = argv[i]
    if (a === '--apply') {
      args.apply = true
    }
    else if (a === '--limit') {
      const v = Number(argv[i + 1]); if (Number.isFinite(v) && v > 0)
        args.limit = Math.floor(v); i++
    }
    else if (a === '--clear-error') {
      args.clearError = true
    }
    else if (a === '--db') {
      const v = argv[i + 1]
      if (v) { args.db = v; i++ }
    }
  }
  return args
}

function nonEmptyRef(ref) {
  return typeof ref === 'string' && ref.trim().length > 0
}

async function main() {
  const args = parseArgs(process.argv)
  // 选择数据库：优先 --db；否则自动探测 userData 路径；最后回退到仓库内开发库
  const candidates = []
  if (args.db) {
    candidates.push(args.db)
  }
  const appdata = process.env.APPDATA || ''
  if (process.platform === 'win32' && appdata) {
    candidates.push(path.join(appdata, 'AutoTools', 'data', 'app.db'))
    candidates.push(path.join(appdata, 'auto-tools', 'data', 'app.db'))
  }
  // 仓库内开发库（很可能不是当前运行库，仅作为兜底）
  candidates.push(path.resolve(process.cwd(), 'app', 'prisma', 'data', 'app.db'))

  let picked = ''
  for (const p of candidates) {
    try { if (p && existsSync(p)) { picked = p; break } }
    catch {}
  }
  if (!picked) {
    console.error('[ERROR] 未找到数据库文件。可使用 --db 指定绝对路径，如 C:/Users/Administrator/AppData/Roaming/AutoTools/data/app.db')
    process.exit(2)
  }
  const dbUrl = `file:${picked.replace(/\\/g, '/')}`
  process.env.DATABASE_URL = dbUrl

  const prisma = new PrismaClient({ datasources: { db: { url: dbUrl } } })
  const mode = args.apply ? 'apply' : 'dry-run'
  console.log(`[INFO] 修复脚本启动 | 模式=${mode} | limit=${args.limit || 'ALL'} | clearError=${args.clearError}`)
  console.log(`[INFO] 使用数据库: ${picked}`)

  try {
    // 1) 找到候选：状态为 failed/pending 且存在非空参考号
    const take = args.limit && args.limit > 0 ? args.limit : undefined
    const candidates = await prisma.appointment_management.findMany({
      where: {
        appointment_status: { in: ['failed', 'pending'] },
        NOT: { reference_number: null },
      },
      select: { id: true, appointment_status: true, reference_number: true, booked_at: true, updated_at: true },
      orderBy: { updated_at: 'desc' },
      take,
    })

    const targets = candidates.filter(r => nonEmptyRef(r.reference_number))
    if (targets.length === 0) {
      console.log('[INFO] 未发现“有参考号但状态为 failed/pending”的记录。')
      return
    }

    console.log(`[INFO] 候选 ${targets.length} 条，将尝试更正为 booked。`)

    // 2) 一次性查询这些记录的首次成功 book 时间用于 booked_at 回填
    const ids = targets.map(t => t.id)
    const logs = await prisma.appointment_operation_log.findMany({
      where: { appointment_id: { in: ids }, operation_type: 'book', result_status: 'success' },
      orderBy: { timestamp: 'asc' },
      select: { appointment_id: true, timestamp: true },
    })
    const idToBookedAt = new Map()
    for (const l of logs) {
      if (!idToBookedAt.has(l.appointment_id))
        idToBookedAt.set(l.appointment_id, l.timestamp)
    }

    let updated = 0
    let skipped = 0
    for (const row of targets) {
      const next = { appointment_status: 'booked' }
      // 仅当缺失 booked_at 时回填（优先操作日志时间 → 否则用 updated_at → 否则现在）
      if (!row.booked_at) {
        const ts = idToBookedAt.get(row.id) || row.updated_at || new Date()
        next.booked_at = ts
      }
      if (args.clearError) {
        next.error_message = null
      }

      if (args.apply) {
        try {
          await prisma.appointment_management.update({ where: { id: row.id }, data: next })
          updated++
        }
        catch (e) {
          skipped++
          console.warn(`[WARN] 更新 id=${row.id} 失败:`, e?.message || e)
        }
      }
      else {
        // 预览输出
        console.log(`[DRYRUN] id=${row.id} ${row.appointment_status} -> booked ${next.booked_at ? `(booked_at=${new Date(next.booked_at).toISOString()})` : ''}`)
        updated++
      }
    }

    console.log(`\n[RESULT] 处理完成：${args.apply ? '已更新' : '预计更新'} ${updated} 条，失败/跳过 ${skipped} 条。`)
  }
  finally {
    // 关闭连接
    try { await (new PrismaClient()).$disconnect() }
    catch {}
  }
}

main().catch((err) => {
  console.error('[FATAL] 脚本异常:', err)
  process.exit(1)
})
